﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Media.Imaging;
using System.Windows.Media;
using System.Windows;

namespace WPFGame.Logic
{
    public static class Super
    {

        #region 静态属性

        /// <summary>
        /// 角色图片缓存
        /// 交错数组示例PartImage[a,b][c,d]
        /// a为衣服代号(在本例中也可以理解为身体代号，因为换衣服就相当于换角色身体)
        /// b为武器代号
        /// c为角色朝向代号
        /// d代表当前动作帧所处于整合图中的列数
        /// 本例中1-5列为站立，6-13列为跑动，14-20列为攻击，21-26列为施法，27-34列为死亡
        /// 本例中PartImage = new BitmapSource[10, 20][,];即初步设定有10个角色，20种武器
        /// </summary>
        public static BitmapSource[,][,] PartImage = new BitmapSource[10, 20][,];

        #endregion

        #region 静态方法

        /// <summary>
        /// 拼装角色+装备后切割成系列帧图片并保存进内存(装备角色)
        /// </summary>
        /// <param name="SourcePath">源文件路径</param>
        /// <param name="SavaToPath">保存文件到目标路径</param>
        /// <param name="imgnum">源图片数量</param>
        /// <param name="imgwidth">单位图片宽</param>
        /// <param name="imgheight">单位图片高</param>
        public static void ComposeImage(string SourcePath, string SavaToPath, int imgNum, int imgWidth, int imgHeight)
        {
            System.IO.FileStream fileStream = new System.IO.FileStream(SavaToPath, System.IO.FileMode.Create);
            DrawingVisual drawingVisual = new DrawingVisual();
            DrawingContext drawingContext = drawingVisual.RenderOpen();
            int count = 1;
            for (int i = 0; i < 8; i++)
            {
                for (int j = 0; j < imgNum / 8; j++)
                {
                    drawingContext.DrawImage(new BitmapImage(new Uri(SourcePath + count + "-1.png")), new Rect(j * imgWidth, i * imgHeight, imgWidth, imgHeight));
                    count += 1;
                }
            }
            drawingContext.Close();
            RenderTargetBitmap renderTargetBitmap = new RenderTargetBitmap((imgNum / 8) * imgWidth, 8 * imgHeight, 0, 0, PixelFormats.Pbgra32);
            renderTargetBitmap.Render(drawingVisual);
            PngBitmapEncoder encoder = new PngBitmapEncoder();
            encoder.Frames.Add(BitmapFrame.Create(renderTargetBitmap));
            encoder.Save(fileStream);
            fileStream.Close();
        }

        /// <summary>
        ///  加载角色合成装备图片并缓存
        /// </summary>
        /// <param name="Equipment">装备代号数组</param>
        /// <param name="rowNum">帧合成图行数</param>
        /// <param name="colNum">帧合成图列数</param>
        /// <param name="totalWidth">帧图合成后总宽</param>
        /// <param name="totalHeight">帧图合成后总高</param>
        /// <param name="singleWidth">单帧图宽</param>
        /// <param name="singleHeight">单帧图高</param>
        /// <returns>如果缓存中有则读取缓存，否则返回合成的图片源</returns>
        public static BitmapSource[,] EquipPart(int[] Equipment, int rowNum, int colNum, int totalWidth, int totalHeight, int singleWidth, int singleHeight)
        {
            //Equipment[0]为衣服代号，Equipment[1]为武器代号，本例中装备只由衣服+武器组成
            //假如内存中没有该装备的角色现成图片源则进行读取
            if (PartImage[Equipment[0], Equipment[1]] == null)
            {
                BitmapSource[,] bitmap = new BitmapSource[rowNum, colNum];
                //加载角色衣服(身体)大图
                BitmapSource bitmapSource = new BitmapImage(new Uri(@"Images\Body" + Equipment[0].ToString() + ".gif", UriKind.Relative));
                //假如武器不是0，即如果角色手上有武器而非空手
                if (Equipment[1] != 0)
                {
                    //加载武器大图，并与衣服大图组装
                    BitmapSource bitmapSource1 = new BitmapImage(new Uri(@"Images\Weapon" + Equipment[1].ToString() + ".gif", UriKind.Relative));
                    DrawingVisual drawingVisual = new DrawingVisual();
                    Rect rect = new Rect(0, 0, totalWidth, totalHeight);
                    DrawingContext drawingContext = drawingVisual.RenderOpen();
                    drawingContext.DrawImage(bitmapSource, rect);
                    drawingContext.DrawImage(bitmapSource1, rect);
                    drawingContext.Close();
                    RenderTargetBitmap renderTargetBitmap = new RenderTargetBitmap(totalWidth, totalHeight, 0, 0, PixelFormats.Pbgra32);
                    renderTargetBitmap.Render(drawingVisual);
                    bitmapSource = renderTargetBitmap;
                    //降低图片质量以提高系统性能(由于本身图片已经为低质量的gif类型，因此效果不大)
                    //RenderOptions.SetBitmapScalingMode(bitmapSource, BitmapScalingMode.LowQuality);
                }
                for (int i = 0; i < rowNum; i++)
                {
                    for (int j = 0; j < colNum; j++)
                    {
                        bitmap[i, j] = new CroppedBitmap(bitmapSource, new Int32Rect(j * singleWidth, i * singleHeight, singleWidth, singleHeight));
                    }
                }
                //缓存装备合成图
                PartImage[Equipment[0], Equipment[1]] = bitmap;
                return bitmap;
            }
            else
            {
                //内存中有该装备的角色图片源则从内存中返回合成图，极大提高性能
                return PartImage[Equipment[0], Equipment[1]];
            }
        }

        /// <summary>
        /// 通过正切值获取精灵的朝向代号
        /// </summary>
        /// <param name="targetX">目标点的X值</param>
        /// <param name="targetY">目标点的Y值</param>
        /// <param name="currentX">当前点的X值</param>
        /// <param name="currentY">当前点的Y值</param>
        /// <returns>精灵朝向代号(以北为0顺时针依次1,2,3,4,5,6,7)</returns>
        public static double GetDirectionByTan(double targetX, double targetY, double currentX, double currentY)
        {
            double tan = (targetY - currentY) / (targetX - currentX);
            if (Math.Abs(tan) >= Math.Tan(Math.PI * 3 / 8) && targetY <= currentY)
            {
                return 0;
            }
            else if (Math.Abs(tan) > Math.Tan(Math.PI / 8) && Math.Abs(tan) < Math.Tan(Math.PI * 3 / 8) && targetX > currentX && targetY < currentY)
            {
                return 1;
            }
            else if (Math.Abs(tan) <= Math.Tan(Math.PI / 8) && targetX >= currentX)
            {
                return 2;
            }
            else if (Math.Abs(tan) > Math.Tan(Math.PI / 8) && Math.Abs(tan) < Math.Tan(Math.PI * 3 / 8) && targetX > currentX && targetY > currentY)
            {
                return 3;
            }
            else if (Math.Abs(tan) >= Math.Tan(Math.PI * 3 / 8) && targetY >= currentY)
            {
                return 4;
            }
            else if (Math.Abs(tan) > Math.Tan(Math.PI / 8) && Math.Abs(tan) < Math.Tan(Math.PI * 3 / 8) && targetX < currentX && targetY > currentY)
            {
                return 5;
            }
            else if (Math.Abs(tan) <= Math.Tan(Math.PI / 8) && targetX <= currentX)
            {
                return 6;
            }
            else if (Math.Abs(tan) > Math.Tan(Math.PI / 8) && Math.Abs(tan) < Math.Tan(Math.PI * 3 / 8) && targetX < currentX && targetY < currentY)
            {
                return 7;
            }
            else
            {
                return 4;
            }
        }

        #endregion
    }
}
